package com.zmn.oms.dubbo.impl.statistics;

import com.google.common.collect.Lists;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dio.normal.statistics.MasterOrderStatDIO;
import com.zmn.oms.common.dro.statistics.MasterOrderStatDRO;
import com.zmn.oms.common.dro.statistics.UserOrderStatDRO;
import com.zmn.oms.dubbo.interfaces.statistics.StatOrderRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.services.interfaces.orderencrypt.OrderEncryptService;
import com.zmn.oms.zmn.business.interfaces.statistics.StatOrderBService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilterBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 类描述：订单统计
 *
 * @author heciqi
 * @date 2021/10/28 18:29
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 3000, retries = 0, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class StatOrderRemoteServiceImpl implements StatOrderRemoteService {

    @Autowired
    private OrderWorkEsBService orderWorkEsBService;
    @Autowired
    private StatOrderBService statOrderBService;
    @Resource
    private OrderEncryptService orderEncryptService;

    /**
     * 用户订单统计
     *
     * @param userList
     * @return
     */
    @Override
    public ResponseDTO<UserOrderStatDRO> getUserOrderStat(List<Long> userList) {
        log.info("订单统计-用户订单统计，入参：{}", userList);

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.termsQuery("userId", userList))
                .filter(QueryBuilders.termQuery("isTest", false))
                .filter(QueryBuilders.termQuery("isDuplicate", false))
                .filter(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_REFUND)));

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(queryBuilder)
                //.withPageable(Pageable.unpaged())
                .withPageable(PageRequest.of(0, 1))

                // 下单量
                .addAggregation(AggregationBuilders.filter("orderCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_NEW))))
                // 进行中工单
                .addAggregation(AggregationBuilders.filter("doingOrderCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING))))
                // 进行中投诉
                .addAggregation(AggregationBuilders.filter("doingComplaintCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING))
                        .filter(QueryBuilders.termQuery("complaintStatus", GlobalConsts.YES))))
                // 进行中退款
                .addAggregation(AggregationBuilders.filter("doingRefundCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING))
                        .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_REFUND))))
                // 成功单量
                .addAggregation(AggregationBuilders.filter("successCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_NEW))
                        .filter(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_SUCCESS))))
                // 取消单量
                .addAggregation(AggregationBuilders.filter("cancelCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.rangeQuery("status").lt(OrderStatusConsts.ORDER_STATUS_COMPLETE))
                        .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_NEW))
                        .filter(QueryBuilders.termsQuery("resultStatus", Arrays.asList(OrderStatusConsts.WORK_RESULT_DISCARD, OrderStatusConsts.WORK_RESULT_FAIL)))))
                // 返修单量
                .addAggregation(AggregationBuilders.filter("reworkCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_REWORK))))
                // 有投诉单量
                .addAggregation(AggregationBuilders.filter("complaintOrderCount", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("complaintStatus", GlobalConsts.YES))
                        .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_NEW))))
                // 消费总额
                .addAggregation(AggregationBuilders.filter("totalExpenseAmountFilter", QueryBuilders.existsQuery("completeTime"))
                        .subAggregation(AggregationBuilders.sum("totalExpenseAmountSum").field("totalAmount"))
                )
                .build();

        Aggregations aggregations = orderWorkEsBService.getAggregationsByQuery(build);

        UserOrderStatDRO obj = new UserOrderStatDRO();
        Long orderCount = ((ParsedFilter) aggregations.get("orderCount")).getDocCount();
        obj.setOrderCount(orderCount.intValue());

        Long doingOrderCount = ((ParsedFilter) aggregations.get("doingOrderCount")).getDocCount();
        obj.setDoingOrderCount(doingOrderCount.intValue());

        Long doingComplaintCount = ((ParsedFilter) aggregations.get("doingComplaintCount")).getDocCount();
        obj.setDoingComplaintCount(doingComplaintCount.intValue());

        Long doingRefundCount = ((ParsedFilter) aggregations.get("doingRefundCount")).getDocCount();
        obj.setDoingRefundCount(doingRefundCount.intValue());

        Long successCount = ((ParsedFilter) aggregations.get("successCount")).getDocCount();
        obj.setSuccessCount(successCount.intValue());

        Long cancelCount = ((ParsedFilter) aggregations.get("cancelCount")).getDocCount();
        obj.setCancelCount(cancelCount.intValue());

        Long reworkCount = ((ParsedFilter) aggregations.get("reworkCount")).getDocCount();
        obj.setReworkCount(reworkCount.intValue());

        Long complaintOrderCount = ((ParsedFilter) aggregations.get("complaintOrderCount")).getDocCount();
        obj.setComplaintOrderCount(complaintOrderCount.intValue());

        double totalAmountSum = ((ParsedSum) ((ParsedFilter) aggregations.get("totalExpenseAmountFilter")).getAggregations().get("totalExpenseAmountSum")).getValue();
        obj.setTotalExpenseAmount((int) totalAmountSum);

        log.info("订单统计-用户订单统计，出参：{}", obj);
        return ResponseDTO.success(obj);
    }


    @Override
    public ResponseDTO<MasterOrderStatDRO> getOrderStatByMasterId(MasterOrderStatDIO masterOrderStatDIO) {
        try {
            MasterOrderStatDRO masterOrderStatDRO = statOrderBService.getOrderStatByMasterId(masterOrderStatDIO);
            return ResponseDTO.success(masterOrderStatDRO);
        } catch (Exception e) {
            log.info("通过参数查出失败的订单统计异常:{}", e.getMessage());
            return ResponseDTO.fail(e.getMessage());
        }
    }

    /**
     * 根据手机号查询服务分类
     *
     * @param phone
     * @return
     */
    @Override
    public ResponseDTO<List<Integer>> listServCategoryIdsByPhone(String phone) {
        try {
            if (log.isDebugEnabled()) {
                log.info("listServCategoryIdsByPhone req：{}", phone);
            }

            // 过滤条件
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                    .filter(QueryBuilders.termQuery("contact.phone", orderEncryptService.encrypt(phone)))
                    .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_NEW))
                    .filter(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING));

            NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
            searchQuery.setPageable(PageRequest.of(0, 50));
            searchQuery.addSourceFilter(new FetchSourceFilterBuilder().withIncludes("servCategId").build());
            List<EsOrderWork> servCategIdList = orderWorkEsBService.listPageByQuery(searchQuery);
            if (CollectionUtil.isNullOrEmpty(servCategIdList)) {
                return ResponseDTO.success(Lists.newArrayList());
            }
            List<Integer> collect = servCategIdList.stream().map(EsOrderWork::getServCategId).
                    distinct().collect(Collectors.toList());
            if (log.isDebugEnabled()) {
                log.debug("listServCategoryIdsByPhone rsp：{} {}", phone, collect);
            }
            return ResponseDTO.success(collect);
        } catch (Exception ex) {
            log.error("listServCategoryIdsByPhone {} ex:{}", phone, ex);
            return ResponseDTO.fail("查询失败");
        }

    }
}
